import { showLoading } from '@uni-helper/uni-promises'
import globalVariable from '@/utils/globalVariable'

const debounceTime = 600

export interface ReuqestConfigDto {
    notLoading?: boolean
    headers?: { [key: string]: string }
    timeout?: number
    noError?: boolean
}

export class Request {
    baseUrl = ''
    returnAll = false
    requestNum = 0

    constructor(url: string) {
        this.baseUrl = url // 基础url
    }

    getHeader(config: ReuqestConfigDto) {
        const headers = {
            ...config.headers,
            appId: globalVariable.appId,
        } as AnyObject
        if (globalVariable.token) {
            const prefix = globalVariable.platForm === 'mp-alipay' ? 'Alipay ' : 'Wx '
            headers.Authorization = prefix + globalVariable.token
        }

        if (globalVariable.platForm)
            headers.platForm = globalVariable.platForm

        return headers
    }

    request(
        url: string,
        data: AnyObject,
        config: ReuqestConfigDto,
        method: 'GET' | 'POST' | 'PUT' | 'DELETE',
    ): Promise<any> {
        const object = {
            url,
            header: config?.headers || {},
            timeout: config?.timeout || 20000,
            data,
            method,
        }
        // 对loading处理
        if (!config.notLoading) {
            if (this.requestNum === 0) {
                setTimeout(() => {
                    if (this.requestNum > 0) {
                        showLoading({
                            title: '加载中...',
                        })
                    }
                }, 600)
            }
            this.requestNum += 1
        }

        // url无https头则视为使用baseUrl
        if (!/^https:\/\/|^http:\/\//.test(url))
            object.url = this.baseUrl + url

        // header处理
        object.header = this.getHeader(config)

        // 开始执行
        return new Promise((resolve, reject) => {
            uni.request({
                ...object,
                success: async (res) => {
                    const result = res.data as AnyObject
                    if (res.statusCode === 401 || res.statusCode === 600 || res.statusCode === 424) {
                        // user.exit()
                        toast(result?.msg)
                        return
                    }
                    if (
                        res.statusCode > 300
                        || res.statusCode < 200
                        || result.code === 500
                    ) {
                        uni.hideLoading()
                        await wait(100)
                        if (!config.noError)
                            toast(result.msg ? result.msg : '请求错误')

                        reject((result.data === undefined || result.data === null) ? result : result.data)
                    }
                    else {
                        resolve(
                            result.data === undefined ? result : result.data,
                        )
                    }
                },
                async fail(err) {
                    const error = err as AnyObject
                    uni.hideLoading()
                    await wait(100)
                    if (!config.noError) {
                        toast(
                            error.data
                                ? error.data.error
                                : '网络错误，请检查网络后重试',
                        )
                    }
                    reject(err)
                },
                complete: () => {
                    if (!config.notLoading) {
                        setTimeout(() => {
                            if (this.requestNum === 0)
                                uni.hideLoading()
                        }, 100)
                        this.requestNum -= 1
                    }
                },
            })
        })
    }

    // post请求
    post(url: string, data: AnyObject = {}, config: ReuqestConfigDto = {}) {
        return new Promise((resolve) => {
            debounce(() => {
                resolve(this.request(url, data, config, 'POST'))
            }, debounceTime, url + JSON.stringify(data))
        })
    }

    // get请求
    get(url: string, data: AnyObject = {}, config: ReuqestConfigDto = {}) {
        return this.request(url, data, config, 'GET')
    }

    // put请求
    put(url: string, data: AnyObject = {}, config: ReuqestConfigDto = {}) {
        return new Promise((resolve) => {
            debounce(() => {
                resolve(this.request(url, data, config, 'PUT'))
            }, debounceTime, url)
        })
    }

    // delete请求
    delete(url: string, data: AnyObject = {}, config: ReuqestConfigDto = {}) {
        return new Promise((resolve) => {
            debounce(() => {
                resolve(this.request(url, data, config, 'DELETE'))
            }, debounceTime, url)
        })
    }
}

// 初始化基础请求接口
export default new Request(`${globalVariable.baseUrl}`)
